package org.lgiavedoni.android.franq.service.communication;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.lgiavedoni.android.franq.core.communication.ChannelKey;
import org.lgiavedoni.android.franq.core.communication.CommunicationChannel;
import org.lgiavedoni.android.franq.core.communication.CommunicationChannelTherad;
import org.lgiavedoni.android.franq.core.communication.CommunicationSource;
import org.lgiavedoni.android.franq.core.message.MessageIn;
import org.lgiavedoni.android.franq.core.message.MessageInterceptor;
import org.lgiavedoni.android.franq.core.message.MessageOut;
import org.lgiavedoni.android.franq.core.service.Service;
import org.lgiavedoni.android.franq.core.speak.CommonPhrase;
import org.lgiavedoni.android.franq.service.log.Logger;
import org.lgiavedoni.android.franq.util.implementation.ImplementationUtil;
import org.lgiavedoni.android.franq.util.phone.AccountUtil;
import org.lgiavedoni.android.franq.util.string.StringUtil;

public class CommunicationService extends Service {

	public static final CommunicationService inst = new CommunicationService();

	private final List<CommunicationSource> communications = new ArrayList<CommunicationSource>();

	private final HashMap<ChannelKey, CommunicationChannel> channels = new HashMap<ChannelKey, CommunicationChannel>();

	private CommunicationService() {
	}

	public CommunicationChannel getChannel() {
		if (Thread.currentThread() instanceof CommunicationChannelTherad)
			return ((CommunicationChannelTherad) Thread.currentThread()).getChannel();

		return null;
	}

	public void sendMessage(MessageOut message) {
		try {
			if (getChannel() != null) {
				getChannel().sendMessage(message);
				return;
			}
			for (CommunicationChannel cc : channels.values()) {
				if (!cc.isBusy())
					cc.sendMessage(message);
			}
		} catch (Exception ex) {
			Logger.inst.error(ex);
		}
	}

	public void sendDefaultTextMessage(String message) {
		sendMessage(MessageOut.create(message));
	}

	public void sendMessage(CommonPhrase phrase) {
		if (phrase != null)
			sendDefaultTextMessage(phrase.getValue());
	}

	public void reciveMessage(final MessageIn message) {
		ChannelKey channelKey = ChannelKey.generateKey(message);
		if (channels.get(channelKey) != null) {
			if (channels.get(channelKey).isAlive()) {
				channels.get(channelKey).reciveMessage(message);
				return;
			}
		}
		CommunicationChannel channel = new CommunicationChannel(message.getSource(), message.getUser());
		channels.put(channelKey, channel);
		channels.get(channelKey).reciveMessage(message);
		channel.start();

	}

	/**
	 * Method to know is the user don't want to talk now
	 * 
	 * @param message
	 * @return
	 */
	public boolean isStopCommand(MessageIn message) {
		// TODO improve this method
		if (StringUtil.equals("stop", message.getText())) {
			return true;
		}
		if (StringUtil.equals("not now", message.getText())) {
			return true;
		}
		if (StringUtil.equals("cancel", message.getText())) {
			return true;
		}
		return false;
	}

	public boolean isBusy() {
		for (CommunicationChannel cc : channels.values()) {
			if (cc.isBusy())
				return true;
		}
		return false;
	}

	public void setMessageInterceptor(MessageInterceptor messageInterceptor) {
		for (CommunicationChannel cc : channels.values()) {
			if (!cc.isBusy())
				cc.setMessageInterceptor(messageInterceptor);
		}
	}

	public synchronized void clearMessageInterceptor() {
		for (CommunicationChannel cc : channels.values()) {
			if (!cc.isBusy())
				cc.clearMessageInterceptor();
		}
	}

	@Override
	public String getServiceName() {
		return "communication";
	}

	@Override
	protected void _run() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void stopInternal() throws Exception {
		communications.clear();
		channels.clear();

	}

	@Override
	protected void startInternal() throws Exception {
		for (Object obj : ImplementationUtil.getImplementationsInst(CommunicationSource.class)) {
			CommunicationSource cs = (CommunicationSource) obj;
			communications.add(cs);
			CommunicationChannel channel = new CommunicationChannel(cs, AccountUtil.getUserEmail());
			channels.put(ChannelKey.generateKey(AccountUtil.getUserEmail(), cs), channel);
			channel.start();
		}

	}

}
